﻿using System;
using System.Collections.Generic;
using System.Text;
using EricUtility;
using TVOnline.Entities;

namespace WatchSeriesHelper.Entities
{

    public class TVShowInfo : AbstractLoadingTuple
    {
        public static string NO_EPGUIDE { get { return "-~{|NONE|}~-"; } }
        public static string EPGUIDE_URL { get { return "http://epguides.com/"; } }
        public static string EPGUIDE_USELESS { get { return "(a Titles & Air Dates Guide)"; } }

        private string m_Id;
        private string m_Name;
        private string m_Description = "";
        private int m_LastSeasonViewed = -1;
        private int m_LastEpisodViewed = -1;
        private string m_EpGuideId;
        private TvRageEntry m_TvRage;
        private string m_ImdbId;
        private bool m_EpGuideLoaded;
        private List<SeasonInfo> m_Seasons = new List<SeasonInfo>();

        public string Name { get { return m_Name; } }
        public string Id { get { return m_Id; } }
        public string Description { get { return m_Description; } }
        public SeasonInfo[] Seasons { get { return m_Seasons.ToArray(); } }
        public int NbSeason { get { return m_Seasons.Count; } }
        public string EpGuideId { get { return m_EpGuideId; } set { m_EpGuideId = value; } }
        public string TvRageId { get { return (m_TvRage == null ? null : m_TvRage.ID); } }
        public TvRageEntry TvRage { get { return m_TvRage; } }
        public string ImdbId { get { return m_ImdbId; } }
        public bool EpGuideLoaded { get { return m_EpGuideLoaded && EpGuideId != NO_EPGUIDE; } }
        public string LastViewed
        {
            get
            {
                if (m_LastSeasonViewed == -1 || m_LastEpisodViewed == -1)
                    return "";
                return String.Format("S{0:00}E{1:00}", m_LastSeasonViewed, m_LastEpisodViewed);
            }
        }
        public string SayLastViewed { get { return (m_LastSeasonViewed == -1 || m_LastEpisodViewed == -1) ? "" : "Last viewed episode: " + LastViewed; } }


        public int LastSeasonViewed
        {
            get { return m_LastSeasonViewed; }
            set { m_LastSeasonViewed = value; }
        }

        public int LastEpisodViewed
        {
            get { return m_LastEpisodViewed; }
            set { m_LastEpisodViewed = value; }
        }
        public TVShowInfo(string id, string name)
        {
            m_Id = id;
            m_Name = name;
        }
        public TVShowInfo(string id, string name, string lastViewed) :
            this(id, name)
        {
            if (!String.IsNullOrEmpty(lastViewed))
            {
                m_LastSeasonViewed = int.Parse(lastViewed.Substring(1, 2));
                m_LastEpisodViewed = int.Parse(lastViewed.Substring(4, 2));
            }
        }
        public TVShowInfo(string id, string name, string lastViewedSeason, string lastViewedEpisode) :
            this(id, name)
        {
            m_LastSeasonViewed = int.Parse(lastViewedSeason);
            m_LastEpisodViewed = int.Parse(lastViewedEpisode);
        }
        public TVShowInfo(string id, string name, string lastViewedSeason, string lastViewedEpisode, string epGuidID) :
            this(id, name, lastViewedSeason, lastViewedEpisode)
        {
            m_EpGuideId = epGuidID;
        }
        public TVShowInfo(string id, string name, string lastViewedSeason, string lastViewedEpisode, string epGuidID, Boolean guideLoaded, string imdb, string rage) :
            this(id, name, lastViewedSeason, lastViewedEpisode, epGuidID)
        {
            m_EpGuideLoaded = guideLoaded;
            if (m_EpGuideLoaded)
            {
                m_ImdbId = imdb;
                m_TvRage = new TvRageEntry(rage);
            }
        }
        public TVShowInfo(string id, string name, string lastViewedSeason, string lastViewedEpisode, string epGuidID, Boolean guideLoaded, string imdb, TvRageEntry rage) :
            this(id, name, lastViewedSeason, lastViewedEpisode, epGuidID)
        {
            m_EpGuideLoaded = guideLoaded;
            if (m_EpGuideLoaded)
            {
                m_ImdbId = imdb;
                m_TvRage = rage;
            }
        }
        protected override void OnLoad()
        {
            m_Seasons.Clear();
            string seasonDeb = "<h2 class=\"lists\">";
            string seasonFin = "</h2>";
            int posSeasonDeb = 0;
            string serieSrc = EricUtility.Networking.Gathering.GatheringUtility.GetPageSource("http://watchseries.eu/serie/" + m_Id);

            string descDiv = "<div class=\"show-summary\">";
            int iDescDiv = serieSrc.IndexOf(descDiv);
            if (iDescDiv > 0)
            {
                string descTd = "<td valign=\"top\" style=\"padding:3px\"><p>";
                int iDescTd = serieSrc.IndexOf(descTd, iDescDiv) + descTd.Length;
                int iDescTdEnd = serieSrc.IndexOf("</p></td>");
                m_Description = WebStringUtility.DecodeString(serieSrc.Substring(iDescTd, iDescTdEnd - iDescTd)).Trim();
                m_Description = m_Description.Replace("\t", "");
                m_Description = StringUtility.RemoveHTMLTags(m_Description);
            }
            int id = 0;
            while ((posSeasonDeb = serieSrc.IndexOf(seasonDeb, 1)) >= 0)
            {
                serieSrc = serieSrc.Substring(posSeasonDeb + seasonDeb.Length);
                int posSeasonFin = serieSrc.IndexOf(seasonFin);
                string sName = serieSrc.Substring(0, posSeasonFin);
                sName = sName.Remove(sName.LastIndexOf('('));
                sName = sName.Substring(sName.LastIndexOf('>')+ 1);
                string[] sNameS = sName.Trim().Replace("  ", " ").Split(' ');
                int no = 0;
                if (sNameS.Length < 2 || !int.TryParse(sNameS[1].Trim(), out no))
                    continue;
                sName = String.Format("{0} {1:00}", sNameS[0].Trim(), no);
                SeasonInfo season = new SeasonInfo(this, ++id, sName);
                string epsEnd = "</ul>";
                string epUrlDeb = "<a href=\"../episode/";
                string epUrlFin = ".html";
                string s = serieSrc.Remove(serieSrc.IndexOf(epsEnd));
                int posEpDeb = 0;
                while ((posEpDeb = s.IndexOf(epUrlDeb)) >= 0)
                {
                    s = s.Substring(posEpDeb + epUrlDeb.Length);
                    int posEpUrlFin = s.IndexOf(epUrlFin);
                    string seUrl = s.Substring(0, posEpUrlFin);
                    int eUrl = int.Parse(seUrl.Substring(seUrl.LastIndexOf('-') + 1));

                    string epIdDeb = "Episode ";
                    string epIdFin = "&nbsp;";
                    int posepIdDeb = s.IndexOf(epIdDeb, posEpUrlFin) + epIdDeb.Length;
                    int posepIdFin = s.IndexOf(epIdFin, posepIdDeb);
                    string mystr = s.Substring(posepIdDeb, posepIdFin - posepIdDeb);
                    int eId = int.Parse(mystr);

                    string epNameFin = "</span>";
                    string nbsp = "&nbsp;";
                    int posepNameDeb = posepIdFin + epIdFin.Length;
                    int posepNameFin = s.IndexOf(epNameFin, posepNameDeb);
                    string eName = s.Substring(posepNameDeb, posepNameFin - posepNameDeb);
                    eName = eName.Substring(eName.LastIndexOf(nbsp) + nbsp.Length);

                    EpisodeInfo ep = new EpisodeInfo(season, eUrl, eId, eName);
                    season.AddEpisode(ep);
                }
                if (season.NbEpisodes > 0)
                    AddSeason(season);
            }
            LoadEpGuide();
            LoadTVRage();
        }

        public void LoadTVRage()
        {
            if (m_EpGuideLoaded && m_TvRage != null)
            {
                if (m_TvRage.NextAiredDate < DateTime.Now)
                    m_TvRage.NeedToReload();
                m_TvRage.LoadIfNeeded();
            }
        }
        public void LoadEpGuide()
        {
            if (!String.IsNullOrEmpty(m_EpGuideId) && m_EpGuideId != NO_EPGUIDE && !m_EpGuideLoaded)
            {
                string res = EricUtility.Networking.Gathering.GatheringUtility.GetPageSource(EPGUIDE_URL + m_EpGuideId);
                m_ImdbId = StringUtility.Extract(res, "http://us.imdb.com/title/", "\"");
                m_TvRage = new TvRageEntry(StringUtility.Extract(res, "http://www.tvrage.com/shows/", "/"));
                m_EpGuideLoaded = true;
            }
        }
        private void AddSeason(SeasonInfo s)
        {
            m_Seasons.Add(s);
        }

        public string SeasonsToString()
        {
            LoadIfNeeded();
            string str = ">>> " + ToString() + " <<<" + Environment.NewLine + Environment.NewLine;

            foreach (SeasonInfo season in m_Seasons)
            {
                str += season.Name + Environment.NewLine;
                foreach (EpisodeInfo ep in season.Episodes)
                {
                    str += "   - " + ep + Environment.NewLine;
                }
            }
            return str;
        }
        public string DescriptionToString()
        {
            LoadIfNeeded();
            string str = ">>> " + ToString() + " <<<" + Environment.NewLine + Environment.NewLine;

            str += m_Description;
            return str;
        }
        public override string ToString()
        {
            return m_Name;
        }
        public override bool Equals(object obj)
        {
            if( !(obj is  TVShowInfo))
                return base.Equals(obj);
            TVShowInfo info = obj as TVShowInfo;
            return Id.Equals(info.Id);
        }
    }
}
